package com.tinyseed.emcp.api.app.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;


@Configuration
@EnableJpaRepositories(basePackages = "com.tinyseed",entityManagerFactoryRef = "customerEntityManager", transactionManagerRef = "customerTransactionManager")
@EnableTransactionManagement
public class MutiplyDataSource {

//
    @Autowired(required = false)
    private PersistenceUnitManager persistenceUnitManager;

    @Bean
    @Primary
    public JpaProperties customerJpaProperties() {
        return new JpaProperties();
    }


    @Resource
    private DataSource dataSource;

    /**
     * 创建 emcp 数据源
     */

    @Primary //设置默认的数据源，避免造成冲突，可能有优化的写法。
    @Bean(name = "emcp")
    @ConfigurationProperties(prefix = "spring.shardingsphere.datasource.emcp") // 读取 spring.datasource.orders 配置到 HikariDataSource 对象
    public DataSource emcp() {
        return DruidDataSourceBuilder.create().build();
    }


    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();

        Map<Object, Object> dataSourceMap = new HashMap<Object, Object>(3);
        DataSource dataSource = this.dataSource;
        dataSourceMap.put("sharding", dataSource);

        dynamicRoutingDataSource.setDefaultTargetDataSource(emcp());
        dynamicRoutingDataSource.setTargetDataSources(dataSourceMap);
        DynamicDataSourceContextHolder.dataSourceKeys.addAll(dataSourceMap.keySet());

        return dynamicRoutingDataSource;

    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean customerEntityManager(
            final JpaProperties customerJpaProperties) {

        //hibernate配置，数据库字段驼峰转下划线，因为这里重新创建jpa实例，所以yml的配置文件基本无法使用。
        HibernateProperties hibernateProperties1 = new HibernateProperties();
        hibernateProperties1.getNaming().setPhysicalStrategy("org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");

        Map<String, Object> properties = hibernateProperties1.determineHibernateProperties(
                customerJpaProperties.getProperties(), new HibernateSettings());


        EntityManagerFactoryBuilder builder =
                createEntityManagerFactoryBuilder(customerJpaProperties);

        return builder.dataSource(dynamicDataSource()).properties(properties).packages("com.tinyseed")
                .persistenceUnit("customerEntityManager").build();
    }

    private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(
            JpaProperties customerJpaProperties) {
        JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(customerJpaProperties);

        return new EntityManagerFactoryBuilder(jpaVendorAdapter,
                customerJpaProperties.getProperties(), this.persistenceUnitManager);
    }
//
    private JpaVendorAdapter createJpaVendorAdapter(
            JpaProperties jpaProperties) {
        AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();

        adapter.setShowSql(jpaProperties.isShowSql());
        adapter.setDatabase(jpaProperties.getDatabase());
        adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
        adapter.setGenerateDdl(jpaProperties.isGenerateDdl());

        return adapter;
    }

    @Bean
    @Primary
    public JpaTransactionManager customerTransactionManager(
            @Qualifier("customerEntityManager") final EntityManagerFactory factory) {
        return new JpaTransactionManager(factory);
    }

}

